#pragma once

#include <iostream>
#include <cstdio>
#include <cstdarg>
#include <ctime>
#include <string>



// 日志是有日志级别的
#define DEBUG   0
#define NORMAL  1//正常
#define WARNING 2//警告
#define ERROR   3//错误
#define FATAL   4//致命

const char *gLevelMap[] = {
    "DEBUG",
    "NORMAL",
    "WARNING",
    "ERROR",
    "FATAL"
};

#define LOGFILE "./threadpool.log"

// 完整的日志功能，至少: 日志等级 时间 支持用户自定义(日志内容, 文件行，文件名)
void logMessage(int level, const char *format, .../*可变参数*/)
{
#ifndef DEBUG_SHOW//条件编译，ifdef满足条件则执行，ifndef如果不满足条件则执行
    if(level== DEBUG) return;
#endif

    //对可变参数列表的操作
    // va_list ap;-char类型的指针
    // va_start(ap, format);-用format来初始化ap，让ap指向栈桢对应的结构，因为压栈在参数列表是从左到右的，所以format先压栈，可变参数后压栈的，ap就指向了可变参数列表的起始位置。
    // while()
    // int x = va_arg(ap, int);//遍历栈，提取一个int类型的整数
    // va_end(ap); //ap=nullptr


    char stdBuffer[1024]; //标准部分
    time_t timestamp = time(nullptr);//参数是时区，不传默认为标准时区
    // struct tm *localtime = localtime(&timestamp);//时间戳转化为时间
    snprintf(stdBuffer, sizeof stdBuffer, "[%s] [%ld] ", gLevelMap[level], timestamp);


    char logBuffer[1024]; //自定义部分
    va_list args;//实际上就是char类型指针
    va_start(args, format);//初始化指针，指向format之后
    // vprintf(format, args);//格式化打印到显示器
    vsnprintf(logBuffer, sizeof logBuffer, format, args);//v格式化显示-解析了format里面的格式，再打印到字符串里面
    va_end(args);//可变参数使用结束,args=nullptr

    FILE *fp = fopen(LOGFILE, "a");
    // printf("%s%s\n", stdBuffer, logBuffer);
    // fprintf(fp, "%s%s\n", stdBuffer, logBuffer);//标准部分和自定义部分都打印到文件里面
    printf( "%s%s\n", stdBuffer, logBuffer);//标准部分和自定义部分都打印到显示器里面
    fclose(fp);
}